package com.imis.base.util.table.service.impl;

import com.imis.base.constant.CommonConstant;
import com.imis.base.constant.DataBaseConstant;
import com.imis.base.constant.enums.CommonResponseEnum;
import com.imis.base.globle.exception.BusinessException;
import com.imis.base.util.ConvertUtils;
import com.imis.base.util.table.model.ColumnMeta;
import com.imis.base.util.table.service.IDataBaseTableHandleService;
import com.imis.module.online.table.model.po.TableIndex;

/**
 * <p>
 * DataBaseTablePostgresHandleServiceImpl<br>
 * Postgres 数据库表处理服务 实现
 * </p>
 *
 * @author XinLau
 * @version 1.0
 * @since 2020年09月28日 17:36
 */
public class DataBaseTablePostgresHandleServiceImpl implements IDataBaseTableHandleService {

    /**
     * 获取添加字段描述
     *
     * @param formColumnMeta - 前端表单
     * @return String - SQL语句
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/10 14:17
     */
    private String getAddFieldDesc(final ColumnMeta formColumnMeta) {
        StringBuilder sql = new StringBuilder();
        if (formColumnMeta.getColumnType().equalsIgnoreCase(DataBaseConstant.STRING)) {
            sql.append(formColumnMeta.getColumnName()).append(DataBaseConstant.SPACE).append(DataBaseConstant.CHARACTER_VARYING).append(DataBaseConstant.LEFT_BRACKET).append(formColumnMeta.getColumnSize()).append(DataBaseConstant.RIGHT_BRACKET).append(DataBaseConstant.SPACE);
        } else if (DataBaseConstant.DATE.equalsIgnoreCase(formColumnMeta.getColumnType())) {
            sql.append(formColumnMeta.getColumnName()).append(DataBaseConstant.SPACE).append(DataBaseConstant.TIMESTAMP_).append(DataBaseConstant.SPACE);
        } else if (DataBaseConstant.INT.equalsIgnoreCase(formColumnMeta.getColumnType())) {
            sql.append(formColumnMeta.getColumnName()).append(DataBaseConstant.SPACE).append(DataBaseConstant.INT4);
        } else if (formColumnMeta.getColumnType().equalsIgnoreCase(DataBaseConstant.DOUBLE)) {
            sql.append(formColumnMeta.getColumnName()).append(DataBaseConstant.SPACE).append(DataBaseConstant.NUMERIC).append(DataBaseConstant.LEFT_BRACKET).append(formColumnMeta.getColumnSize()).append(DataBaseConstant.COMMA).append(formColumnMeta.getDecimalDigits()).append(DataBaseConstant.RIGHT_BRACKET).append(DataBaseConstant.SPACE);
        } else if (DataBaseConstant.BIG_DECIMAL.equalsIgnoreCase(formColumnMeta.getColumnType())) {
            sql.append(formColumnMeta.getColumnName()).append(DataBaseConstant.SPACE).append(DataBaseConstant.DECIMAL).append(DataBaseConstant.LEFT_BRACKET).append(formColumnMeta.getColumnSize()).append(DataBaseConstant.COMMA).append(formColumnMeta.getDecimalDigits()).append(DataBaseConstant.RIGHT_BRACKET).append(DataBaseConstant.SPACE);
        } else if (DataBaseConstant.BLOB_.equalsIgnoreCase(formColumnMeta.getColumnType())) {
            sql.append(formColumnMeta.getColumnName()).append(DataBaseConstant.SPACE).append(DataBaseConstant.BYTEA_).append(DataBaseConstant.LEFT_BRACKET).append(formColumnMeta.getColumnSize()).append(DataBaseConstant.RIGHT_BRACKET).append(DataBaseConstant.SPACE);
        } else if (DataBaseConstant.TEXT.equalsIgnoreCase(formColumnMeta.getColumnType())) {
            sql.append(formColumnMeta.getColumnName()).append(DataBaseConstant.SPACE).append(DataBaseConstant.TEXT_).append(DataBaseConstant.SPACE);
        }
        sql.append((ConvertUtils.isNotEmpty(formColumnMeta.getColumnDefaultValue()) ? DataBaseConstant.SQL_DEFAULT + formColumnMeta.getColumnDefaultValue() : DataBaseConstant.SPACE));
        return sql.toString();
    }

    /**
     * 获取重命名字段描述
     *
     * @param formColumnMeta - 前端表单
     * @return String - SQL语句
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/10 14:17
     */
    private String getRenameFieldDesc(final ColumnMeta formColumnMeta) {
        StringBuilder sql = new StringBuilder();
        if (DataBaseConstant.STRING.equalsIgnoreCase(formColumnMeta.getColumnType())) {
            sql.append(formColumnMeta.getColumnName()).append(DataBaseConstant.SPACE).append(DataBaseConstant.CHARACTER_VARYING).append(DataBaseConstant.LEFT_BRACKET).append(formColumnMeta.getColumnSize()).append(DataBaseConstant.RIGHT_BRACKET).append(DataBaseConstant.SPACE);
        } else if (DataBaseConstant.DATE.equalsIgnoreCase(formColumnMeta.getColumnType())) {
            sql.append(formColumnMeta.getColumnName()).append(DataBaseConstant.DATE_TIME_).append(DataBaseConstant.SPACE);
        } else if (DataBaseConstant.INT.equalsIgnoreCase(formColumnMeta.getColumnType())) {
            sql.append(formColumnMeta.getColumnName()).append(DataBaseConstant.SPACE).append(DataBaseConstant.INT).append(DataBaseConstant.LEFT_BRACKET).append(formColumnMeta.getColumnSize()).append(DataBaseConstant.RIGHT_BRACKET).append(DataBaseConstant.SPACE);
        } else if (DataBaseConstant.DOUBLE.equalsIgnoreCase(formColumnMeta.getColumnType())) {
            sql.append(formColumnMeta.getColumnName()).append(DataBaseConstant.NUMERIC_).append(DataBaseConstant.LEFT_BRACKET).append(formColumnMeta.getColumnSize()).append(DataBaseConstant.COMMA).append(formColumnMeta.getDecimalDigits()).append(DataBaseConstant.RIGHT_BRACKET).append(DataBaseConstant.SPACE);
        }
        return sql.toString();
    }

    /**
     * 获取更新字段描述
     *
     * @param formColumnMeta - 前端表单
     * @param dataColumnMeta - 数据库表
     * @return String - SQL语句
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/10 14:17
     */
    private String getUpdateFieldDesc(final ColumnMeta formColumnMeta, final ColumnMeta dataColumnMeta) {
        StringBuilder sql = new StringBuilder();
        // TODO:This：对于非空情况，需要特殊增加约束方法，默认是空
        if (formColumnMeta.getColumnType().equalsIgnoreCase(DataBaseConstant.STRING)) {
            sql.append(formColumnMeta.getColumnName()).append(DataBaseConstant.SQL_TYPE).append(DataBaseConstant.CHARACTER_VARYING).append(DataBaseConstant.LEFT_BRACKET).append(formColumnMeta.getColumnSize()).append(DataBaseConstant.RIGHT_BRACKET).append(DataBaseConstant.SPACE);
        } else if (DataBaseConstant.DATE_.equalsIgnoreCase(formColumnMeta.getColumnType())) {
            sql.append(formColumnMeta.getColumnName()).append(DataBaseConstant.SQL_TYPE).append(DataBaseConstant.TIMESTAMP_).append(DataBaseConstant.SPACE);
        } else if (DataBaseConstant.INT.equalsIgnoreCase(formColumnMeta.getColumnType())) {
            // postpres 数据库整形没有长度概念
            sql.append(formColumnMeta.getColumnName()).append(DataBaseConstant.SQL_TYPE).append(DataBaseConstant.INT4).append(DataBaseConstant.SPACE);
        } else if (DataBaseConstant.DOUBLE.equalsIgnoreCase(formColumnMeta.getColumnType())) {
            sql.append(formColumnMeta.getColumnName()).append(DataBaseConstant.SQL_TYPE).append(DataBaseConstant.NUMERIC_).append(DataBaseConstant.LEFT_BRACKET).append(formColumnMeta.getColumnSize()).append(DataBaseConstant.COMMA).append(formColumnMeta.getDecimalDigits()).append(DataBaseConstant.RIGHT_BRACKET).append(DataBaseConstant.SPACE);
        } else if (DataBaseConstant.BIG_DECIMAL.equalsIgnoreCase(formColumnMeta.getColumnType())) {
            sql.append(formColumnMeta.getColumnName()).append(DataBaseConstant.SQL_TYPE).append(DataBaseConstant.DECIMAL).append(DataBaseConstant.LEFT_BRACKET).append(formColumnMeta.getColumnSize()).append(DataBaseConstant.COMMA).append(formColumnMeta.getDecimalDigits()).append(DataBaseConstant.RIGHT_BRACKET).append(DataBaseConstant.SPACE);
        } else if (DataBaseConstant.TEXT_.equalsIgnoreCase(formColumnMeta.getColumnType())) {
            sql.append(formColumnMeta.getColumnName()).append(DataBaseConstant.SPACE).append(DataBaseConstant.TEXT_).append(DataBaseConstant.SPACE);
        } else if (DataBaseConstant.BLOB_.equalsIgnoreCase(formColumnMeta.getColumnType())) {
            // bytea 类型不可修改，修改会报错
            CommonResponseEnum.ERROR_500.assertFail();
        }
        return sql.toString();
    }

    /**
     * 获取更新字段默认值
     *
     * @param formColumnMeta - 前端表单
     * @param dataColumnMeta - 数据库表
     * @return String - SQL语句
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/10 14:17
     */
    private String getUpdateFieldDefault(final ColumnMeta formColumnMeta, final ColumnMeta dataColumnMeta) {
        StringBuilder sql = new StringBuilder();
        if (!formColumnMeta.equalsDefault(dataColumnMeta)) {
            if (formColumnMeta.getColumnType().equalsIgnoreCase(DataBaseConstant.STRING)) {
                sql.append(formColumnMeta.getColumnName())
                        .append((ConvertUtils.isNotEmpty(formColumnMeta.getColumnDefaultValue()) ? DataBaseConstant.SQL_SET_DEFAULT + formColumnMeta.getColumnDefaultValue() : DataBaseConstant.SQL_DROP_DEFAULT));
            } else if (DataBaseConstant.DATE_.equalsIgnoreCase(formColumnMeta.getColumnType())) {
                sql.append(formColumnMeta.getColumnName())
                        .append((ConvertUtils.isNotEmpty(formColumnMeta.getColumnDefaultValue()) ? DataBaseConstant.SQL_SET_DEFAULT + formColumnMeta.getColumnDefaultValue() : DataBaseConstant.SQL_DROP_DEFAULT));
            } else if (DataBaseConstant.INT.equalsIgnoreCase(formColumnMeta.getColumnType())) {
                sql.append(formColumnMeta.getColumnName())
                        .append((ConvertUtils.isNotEmpty(formColumnMeta.getColumnDefaultValue()) ? DataBaseConstant.SQL_SET_DEFAULT + formColumnMeta.getColumnDefaultValue() : DataBaseConstant.SQL_DROP_DEFAULT));
            } else if (formColumnMeta.getColumnType().equalsIgnoreCase(DataBaseConstant.DOUBLE)) {
                sql.append(formColumnMeta.getColumnName())
                        .append((ConvertUtils.isNotEmpty(formColumnMeta.getColumnDefaultValue()) ? DataBaseConstant.SQL_SET_DEFAULT + formColumnMeta.getColumnDefaultValue() : DataBaseConstant.SQL_DROP_DEFAULT));
            } else if (DataBaseConstant.BIG_DECIMAL_.equalsIgnoreCase(formColumnMeta.getColumnType())) {
                sql.append(formColumnMeta.getColumnName())
                        .append((ConvertUtils.isNotEmpty(formColumnMeta.getColumnDefaultValue()) ? DataBaseConstant.SQL_SET_DEFAULT + formColumnMeta.getColumnDefaultValue() : DataBaseConstant.SQL_DROP_DEFAULT));
            } else if (DataBaseConstant.TEXT_.equalsIgnoreCase(formColumnMeta.getColumnType())) {
                sql.append(formColumnMeta.getColumnName())
                        .append((ConvertUtils.isNotEmpty(formColumnMeta.getColumnDefaultValue()) ? DataBaseConstant.SQL_SET_DEFAULT + formColumnMeta.getColumnDefaultValue() : DataBaseConstant.SQL_DROP_DEFAULT));
            }
        }
        return sql.toString();
    }

    @Override
    public String getAddColumnSql(final ColumnMeta columnMeta) {
        return DataBaseConstant.SQL_ADD + DataBaseConstant.SQL_COLUMN + getAddFieldDesc(columnMeta) + DataBaseConstant.SEMICOLON;
    }

    @Override
    public String getReNameFieldName(final ColumnMeta columnMeta) {
        return DataBaseConstant.SQL_RENAME + DataBaseConstant.SQL_COLUMN + columnMeta.getOldColumnName() + DataBaseConstant.SQL_TO + columnMeta.getColumnName() + DataBaseConstant.SEMICOLON;
    }

    @Override
    public String getUpdateColumnSql(final ColumnMeta formColumnMeta, final ColumnMeta dataColumnMeta) throws BusinessException {
        return DataBaseConstant.SQL_ALTER + DataBaseConstant.SQL_COLUMN + getUpdateFieldDesc(formColumnMeta, dataColumnMeta) + DataBaseConstant.SEMICOLON;
    }

    @Override
    public String getSpecialHandle(final ColumnMeta formColumnMeta, final ColumnMeta dataColumnMeta) {
        return DataBaseConstant.SQL_ALTER + DataBaseConstant.SQL_COLUMN + getUpdateFieldDefault(formColumnMeta, dataColumnMeta) + DataBaseConstant.SEMICOLON;
    }

    @Override
    public String getMatchClassTypeByDataType(final String dataType, final int digits) {
        String result = DataBaseConstant.EMPTY;
        if (DataBaseConstant.VARCHAR.equalsIgnoreCase(dataType)) {
            result = DataBaseConstant.STRING;
        } else if (DataBaseConstant.DOUBLE.equalsIgnoreCase(dataType)) {
            result = DataBaseConstant.DOUBLE;
        } else if (DataBaseConstant.INT.contains(dataType)) {
            result = DataBaseConstant.INT;
        } else if (DataBaseConstant.DATE.equalsIgnoreCase(dataType)) {
            result = DataBaseConstant.DATE_;
        } else if (DataBaseConstant.TIMESTAMP.equalsIgnoreCase(dataType)) {
            result = DataBaseConstant.DATE_;
        } else if (DataBaseConstant.BYTEA.equalsIgnoreCase(dataType)) {
            result = DataBaseConstant.BLOB_;
        } else if (DataBaseConstant.TEXT_.equalsIgnoreCase(dataType)) {
            result = DataBaseConstant.TEXT_;
        } else if (DataBaseConstant.DECIMAL.equalsIgnoreCase(dataType)) {
            result = DataBaseConstant.BIG_DECIMAL_;
        } else if (DataBaseConstant.NUMERIC.equalsIgnoreCase(dataType)) {
            // double 和 decimal 都会返回 numeric，先暂时返回 bigdecimal
            result = DataBaseConstant.BIG_DECIMAL_;
        }
        return result;
    }

    @Override
    public String dropTableSql(final String tableName) {
        return DataBaseConstant.SQL_DROP + DataBaseConstant.SQL_TABLE + tableName + DataBaseConstant.SEMICOLON;
    }

    @Override
    public String getDropColumnSql(final String fieldName) {
        return DataBaseConstant.SQL_DROP + DataBaseConstant.SQL_COLUMN + fieldName + DataBaseConstant.SEMICOLON;
    }

    @Override
    public String getColumnCommentSql(final ColumnMeta columnMeta) {
        return DataBaseConstant.SQL_COMMENT + DataBaseConstant.SQL_ON + DataBaseConstant.SQL_COLUMN + columnMeta.getTableName() + DataBaseConstant.DOT + columnMeta.getColumnName() + DataBaseConstant.SQL_IS + DataBaseConstant.SINGLE_QUOTE + columnMeta.getColumnComment() + DataBaseConstant.SINGLE_QUOTE;
    }

    @Override
    public String creatIndexes(final TableIndex tableIndex, final String tableName) {
        StringBuilder sql = new StringBuilder();
        if (!CommonConstant.DEL_FLAG_DELETE.equals(tableIndex.getDelFlag()) && CommonConstant.TO_UPPER_CASE_N.equals(tableIndex.getIsSynchronize())) {
            String indexName = tableIndex.getIndexName();
            String indexField = tableIndex.getIndexField();
            String indexType = DataBaseConstant.NORMAL_SYNCHRONIZATION.equals(tableIndex.getIndexType()) ? DataBaseConstant.SQL_INDEX : tableIndex.getIndexType() + DataBaseConstant.SQL_INDEX;
            sql.append(DataBaseConstant.SQL_CREATE).append(indexType).append(indexName).append(DataBaseConstant.SQL_ON).append(tableName).append(DataBaseConstant.LEFT_BRACKET).append(indexField).append(DataBaseConstant.RIGHT_BRACKET);
        }
        return sql.toString();
    }

    @Override
    public String dropIndexes(final String indexName, final String tableName) {
        return DataBaseConstant.SQL_DROP + DataBaseConstant.SQL_INDEX + indexName;
    }

    @Override
    public String countIndex(final String indexName, final String tableName) {
        return DataBaseConstant.SQL_SELECT + DataBaseConstant.SQL_COUNT + DataBaseConstant.SQL_FROM + "pg_indexes" + DataBaseConstant.SQL_WHERE + "indexname" + DataBaseConstant.SPACE + DataBaseConstant.EQUALS + DataBaseConstant.SPACE + DataBaseConstant.SINGLE_QUOTE + indexName + DataBaseConstant.SINGLE_QUOTE + DataBaseConstant.SQL_AND + "tablename" + DataBaseConstant.SPACE + DataBaseConstant.EQUALS + DataBaseConstant.SPACE + DataBaseConstant.SINGLE_QUOTE + tableName + DataBaseConstant.SINGLE_QUOTE;
    }

}
